# -*- coding: utf-8 -*-
import os
import Image, ImageFont, ImageDraw
import pprint
import logging
import re
import datetime
import workerpool
import traceback
import math
from pymongo import Connection
from wlib import *

BG_80_100 = 'Icons/80_100.png'
BG_160_100 = 'Icons/160_100.png'
BG_320_100 = 'Icons/320_100.png'
BG_160_200 = 'Icons/160_200.png' 
FONT = 'Font/verdana.ttf'
FONTB = 'Font/verdanab.ttf'
OUTPUT = 'Output'

class Weather():
    
    def __init__(self, host, port):
        try:
            self.connection = Connection(host, port)
        except:
            logger.error(unicode('Không kết nối được tới database server', 'utf-8'))
        self.dBName = 'thoitiet_v2'
        
    def __del__(self):
        self.connection.end_request()
    
    def getCurrentWeather(self, id):
        db = self.connection[self.dBName]
        collection = db['datlien']
        return collection.find_one({'_id': id})
        
    def imageRenderer(self, idCity):
        logger.debug("call imageRenderer, idCity={0}".format(idCity))
        data = self.getCurrentWeather(idCity)
        self.size4x1(data, idCity)
        self.size2x1(data, idCity)
        self.size1x1(data, idCity)

    def listcity(self):
        db = self.connection[self.dBName]
        collection = db['datlien']
        data = []
        rows = collection.find({}, {'_id': 1})
        if rows:
            for row in rows:
                data.append(row['_id'])
        return data
        
    def detectIcon(self, iconStr):
        now = datetime.datetime.now()
        daylight = True
        if (now.hour <= 4 or now.hour >= 18): daylight = False
#        daylight = True
        iconPath = "Icons/{0}"
        m = re.search(r'/(\d+)\.gif', iconStr)
        iconNo = m.group(1) if m != None else ''
        if iconNo in ['340']:
            icon = "cloudy1.png" if daylight else "cloudy1_night.png"
        elif iconNo in ['110']:
            icon = "shower3.png"
        elif iconNo == '260':
            icon = "cloudy5.png"
        elif iconNo == '390':
            icon = "shower2.png" if daylight else "shower2_night.png"
        elif iconNo == '90':
            icon = "light_rain.png"
        elif iconNo == '90':
            icon = "shower2_night.png"
        elif iconNo == '40':
            icon = "tstorm2.png" if daylight else "tstorm2_night.png"
        else:
            icon = "cloudy2.png" if daylight else "cloudy2_night.png"
        return iconPath.format(icon)
    
    def getFont(self, size=13):
        return ImageFont.truetype(filename=FONT, size=size)
    
    def getFontBold(self, size=14):
        return ImageFont.truetype(filename=FONTB, size=size)
    
    def drawText(self, im, text, xy=(0,0), size=13, color=(255,255,255), type='normal', align=None, valign=None, margin=(0,0,0,0)):
        if im == None: return
        im_w, im_h = im.size
        if type == 'bold':
            font = self.getFontBold(size)
        else:
            font = self.getFont(size)
        t_w, t_h = font.getsize(text)
        if align != None:
            x, y = xy
            if align == 'left':
                xy = (0, y)
            elif align == 'center':
                xy = (im_w/2 - t_w/2, y)
            elif align == 'right':
                xy = (im_w-t_w, y)
        if valign != None:
            x, y = xy
            if valign == 'top':
                xy = (x, 0)
            elif valign == 'middle':
                xy = (x, im_h/2 - t_h/2)
            elif valign == 'bottom':
                xy = (x, im_h-t_h)
        mtop, mright, mbottom, mleft = margin
        dy = mtop - mbottom
        dx = mleft - mright
        if dy < 0:
            xy = (xy[0], xy[1] + dy)
        elif dy > 0:
            xy = (xy[0], xy[1] - dy)
        if dx < 0:
            xy = (xy[0] + dx, xy[1])
        elif dx > 0:
            xy = (xy[0] - dx, xy[1])
        draw = ImageDraw.Draw(im)
        draw.text(xy, text, font=font, fill=color)
        del draw
    
    def size4x1(self, data, idCity):
        logger.debug('call size4x1, parametter idCity={0}'.format(idCity))
        try:
            im = Image.open(BG_320_100)
            im_w, im_h = im.size
            weatherToday = data['bangaytoi'][0]
            maxTemperature = int(weatherToday['nhietdocaonhat'])
            minTemperature = int(weatherToday['nhietdothapnhat'])
            avgTemperature = int((maxTemperature + minTemperature)/2)
            temperatureText = unicode("{0}°C".format(data['nhietdo']), 'utf-8') if data['nhietdo'] != '' else unicode('{0}°C'.format(avgTemperature), 'utf-8')
            self.drawText(im, text=temperatureText, xy=(5, 20), size=28, valign='middle', type='bold')
            self.drawText(im, text=data['provinceName'], xy=(2, 22), size=12, type='normal')
            for i in range(len(data['bangaytoi'])):
                thuName = extractWithRegEx(r'(.+),', data['bangaytoi'][i]['ngay'], 1)
                maxminText = unicode("{0}/{1}°C".format(data['bangaytoi'][i]['nhietdocaonhat'], data['bangaytoi'][i]['nhietdothapnhat']), 'utf-8')
                icon = self.detectIcon(data['bangaytoi'][i]['icon'])
                wicon = Image.open(icon)
                wicon = wicon.resize((60, 60), Image.ANTIALIAS)
                wicon = wicon.convert("RGBA")
                r,g,b,a = wicon.split()
                xy = (95 + i*75, 10)
                im.paste(wicon, xy, mask=a)
                font = self.getFontBold(15)
                t_w, t_h = font.getsize(thuName)
                self.drawText(im, xy=(xy[0]-5, xy[1]+50), text=thuName, size=15, type='bold')
                font = self.getFont(13)
                t1_w, t1_h = font.getsize(maxminText)
                self.drawText(im, xy=(xy[0]-5 + (t_w/2-t1_w/2), xy[1]+65), text=maxminText, size=13, type='normal')
            im.save('{0}/{1}_wg4x1_weather.png'.format(OUTPUT, idCity))
        except:
            logger.error("{0} - {1}".format(idCity, traceback.format_exc()))
        logger.debug("finished size4x1, parametter idCity={0}".format(idCity))
        
    def size2x1(self, data, idCity):
        logger.debug('call size2x1, parametter idCity={0}'.format(idCity))
        try:
            im = Image.open(BG_160_100)
            im_w, im_h = im.size
            weatherToday = data['bangaytoi'][0]
            maxTemperature = int(weatherToday['nhietdocaonhat'])
            minTemperature = int(weatherToday['nhietdothapnhat'])
            avgTemperature = int((maxTemperature + minTemperature)/2)
            icon = self.detectIcon(data['icon']) if data['icon'] != '' else self.detectIcon(weatherToday['icon'])
            maxminText = unicode("{0}/{1}°C".format(weatherToday['nhietdocaonhat'], weatherToday['nhietdothapnhat']), 'utf-8')
            temperatureText = unicode("{0}°C".format(data['nhietdo']), 'utf-8') if data['nhietdo'] != '' else unicode('{0}°C'.format(avgTemperature), 'utf-8')
            wicon = Image.open(icon)
            wicon = wicon.resize((80, 80), Image.ANTIALIAS)
            wicon = wicon.convert("RGBA")
            r,g,b,a = wicon.split()
            im.paste(wicon, (5,im_h /2 - wicon.size[1]/2), mask=a)
            self.drawText(im, text=data['provinceName'], size=12, align='right', valign='bottom', margin=(0,12,5,0))
            self.drawText(im, text=temperatureText, xy=(84, 30), size=26, type='bold')
            self.drawText(im, text=maxminText, xy=(93, 55), size=12)
            im.save('{0}/{1}_wg2x1_weather.png'.format(OUTPUT, idCity))
        except:
            logger.error("{0} - {1}".format(idCity, traceback.format_exc()))
        logger.debug("finished size2x1, parametter idCity={0}".format(idCity))
        
    def size1x1(self, data, idCity):
        logger.debug('call size1x1, parametter idCity={0}'.format(idCity))
        try:
            weatherToday = data['bangaytoi'][0]
            maxTemperature = int(weatherToday['nhietdocaonhat'])
            minTemperature = int(weatherToday['nhietdothapnhat'])
            avgTemperature = int((maxTemperature + minTemperature)/2)
            im = Image.open(BG_80_100)
            im = im.convert("RGBA")
            r,g,b,a = im.split()
            im_w, im_h = im.size
            blank = Image.new("RGBA", (im_w, im_h))
            icon = self.detectIcon(data['icon']) if data['icon'] != '' else self.detectIcon(weatherToday['icon'])
            maxminText = unicode("{0}/{1}°C".format(weatherToday['nhietdocaonhat'], weatherToday['nhietdothapnhat']), 'utf-8')
            temperatureText = unicode("{0}°C".format(data['nhietdo']), 'utf-8') if data['nhietdo'] != '' else unicode('{0}°C'.format(avgTemperature), 'utf-8')
            wicon = Image.open(icon)
            wicon = wicon.resize((60, 60), Image.ANTIALIAS)
            blank.paste(wicon, (im_w/2-wicon.size[0]/2, im_h/2-wicon.size[1]/2))
            self.drawText(im, temperatureText, (0, 1), 16, align='center', type='bold')
            self.drawText(im, maxminText, (0, 78), 14, align='center')
            blank.paste(im, mask=a)
            blank.save('{0}/{1}_wg1x1_weather.png'.format(OUTPUT, idCity))
        except:
            logger.error("{0} - {1}".format(idCity, traceback.format_exc()))
        logger.debug("finished size1x1, parametter idCity={0}".format(idCity))
        
    def process(self):
        logger.debug("call process")
        try:
            cities = self.listcity()
            pool = workerpool.WorkerPool(size=3)
            pool.map(self.imageRenderer, cities)
            pool.shutdown()
            pool.wait()
        except:
            logger.error(traceback.format_exc())
        
if __name__ == '__main__':
    fmt = "%(levelname)-6s - %(asctime)s - %(lineno)-3s - %(msg)s"
    logging.basicConfig(format=fmt)
    logger = logging.getLogger('weather image generator')
    logger.setLevel(logging.DEBUG)
    logger.debug('start weather image generating')
    try:
        w = Weather('beta.mana.vn', 27017)
        w.process()
    except:
        logger.error(traceback.format_exc())
    logger.debug('finished weather image generating at {0}'.format(datetime.datetime.now()))
    os._exit(1)
